My scenario:
I have a server with IP x.x.x.x, on which I run a MongoDB instance. I also build my service with a docker-compose.yml file as below
version: "3"
services:
myApp:
image: myApplication
ports:
- "8080:8080"
environment:
SPRING_DATA_MONGODB_URI: mongodb://localhost:27017/myAppDb
When I run docker-compose up to start the container, I can access my service from my computer via x.x.x.x:8080
But the problem is that my service cannot connect to the mongoDB at localhost:27017, because they're not on the same network. Therefore, I add the option network_mode: "host" to my docker-compose file. It solves the problem, my service can connect to the mongoDB running on my server. However, I cannot access my service via x.x.x.x:8080 anymore
My question:
How can I still connect to my service via x.x.x.x:80 with the option network_mode: "host"? Or is there any way that I don't need to use that option, but my service can still connect to the mongoDB instance?
Note: The MongoDB instance is installed in traditional way (yum install mongodb-org) and set up in a way that it can only be accessed via localhost:27017 (or 127.0.0.1:27107). I don't know why or how but that's the way it is, so I cannot change the connection string to mongodb://x.x.x.x:27017. It just won't work.
I also know that I can add mongodb as a service in the docker-compose file to achieve my goal, but I don't want to do that since in my case, it's better to manage database separately.
It seems that the only way out is to run the myApp container in host mode. In this mode the service should be reachable at the IP address of the host on port 8080.
If it's not, that's most probably because of firewalling issues.
The same service can be accessed in bridge network mode, as in this mode, docker manipulates iptables rules to provide access to containers. More info here.
In your specific case docker adds a NAT rule to forward incoming traffic at port 8080 on the host to port 8080 on the container. Executing iptables
iptables -t nat -L
should output the rule:
Chain POSTROUTING (policy ACCEPT)
MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:http-alt
...
Chain DOCKER (2 references)
DNAT tcp -- anywhere anywhere tcp dpt:http-alt to:172.17.0.2:8080
where 172.17.0.2 is the IP of the container.
The problem is in host mode where the publish ports are discarded and docker doesn't add any rule to allow the incoming traffic through port 8080. You have to add the rule yourself.
Hope it helps.
I have experienced something similar, but i didn't use docker-compose, but i think you might be able to apply the same method.
In stead of using host, you will create your own bridge network(https://docs.docker.com/network/bridge/), and then i think your service should be able to access the mongodb, and you should be able to access the mongodb too :)